import Foundation
import CoreMotion
import UniformTypeIdentifiers

// MARK: - 数据模型

/// 原始传感器数据样本（加速度计 + 陀螺仪）
struct RawSample: Codable {
    let t: TimeInterval          // 时间戳
    let ax: Double                // 加速度 X（包含重力）
    let ay: Double                // 加速度 Y（包含重力）
    let az: Double                // 加速度 Z（包含重力）
    let wx: Double                // 陀螺仪 X（旋转速率，rad/s）
    let wy: Double                // 陀螺仪 Y（旋转速率，rad/s）
    let wz: Double                // 陀螺仪 Z（旋转速率，rad/s）
}

/// 线性加速度样本（去除重力，世界坐标系）
struct LinSample: Codable {
    let t: TimeInterval          // 时间戳
    let ax_lin: Double            // 线性加速度 X
    let ay_lin: Double            // 线性加速度 Y
    let az_lin: Double            // 线性加速度 Z
}

// MARK: - 传感器记录器

final class SensorRecorder: NSObject, ObservableObject {
    // MARK: - 私有属性
    
    private let headphoneMotionManager = CMHeadphoneMotionManager()
    
    // MARK: - 发布属性
    
    /// 是否正在录制
    @Published var isRunning: Bool = false
    
    // 数据缓冲区
    @Published var rawSamples: [RawSample] = []
    @Published var linSamples: [LinSample] = []
    
    // 实时数据（用于 UI 展示）
    @Published var currentAccX: Double = 0      // 加速度 X（包含重力）
    @Published var currentAccY: Double = 0      // 加速度 Y（包含重力）
    @Published var currentAccZ: Double = 0      // 加速度 Z（包含重力）
    @Published var currentGyroX: Double = 0     // 陀螺仪 X（rad/s）
    @Published var currentGyroY: Double = 0     // 陀螺仪 Y（rad/s）
    @Published var currentGyroZ: Double = 0     // 陀螺仪 Z（rad/s）
    
    // 实时图表数据（保留最近100个数据点）
    @Published var accXHistory: [Double] = []
    @Published var accYHistory: [Double] = []
    @Published var accZHistory: [Double] = []
    @Published var gyroXHistory: [Double] = []
    @Published var gyroYHistory: [Double] = []
    @Published var gyroZHistory: [Double] = []
    private let maxHistoryPoints = 100
    @Published var sampleCount: Int = 0
    
    // MARK: - 初始化
    
    override init() {
        super.init()
        print("🚀 [SensorRecorder] 初始化完成")
        print("📱 [SensorRecorder] isDeviceMotionAvailable: \(headphoneMotionManager.isDeviceMotionAvailable)")
        print("🔐 [SensorRecorder] authorizationStatus: \(CMHeadphoneMotionManager.authorizationStatus().rawValue)")
        
        #if targetEnvironment(simulator)
        print("⚠️ [SensorRecorder] 运行在模拟器上，CMHeadphoneMotionManager 不支持！")
        #else
        print("✅ [SensorRecorder] 运行在真机上")
        #endif
        
        // 设置 delegate（教程中的关键步骤）
        headphoneMotionManager.delegate = self
    }
    
    // MARK: - 录制控制
    
    /// 开始录制传感器数据
    func start(rateHz: Double = 50) {
        guard !isRunning else {
            print("⚠️ [SensorRecorder] 已在录制中")
            return
        }
        
        // 检查设备是否支持
        guard headphoneMotionManager.isDeviceMotionAvailable else {
            print("❌ [SensorRecorder] 设备不支持头部运动数据")
            print("   请确保：")
            print("   1. 已连接支持的 AirPods (AirPods 3代、Pro、Max)")
            print("   2. 已授权运动与健身权限")
            return
        }
        
        print("🔄 [SensorRecorder] 启动传感器监听")
        print("📊 [SensorRecorder] 当前状态 - isDeviceMotionActive: \(headphoneMotionManager.isDeviceMotionActive)")
        isRunning = true
        
        // 清空数据缓冲区
        rawSamples.removeAll()
        linSamples.removeAll()
        sampleCount = 0
        
        // 清空历史数据
        accXHistory.removeAll()
        accYHistory.removeAll()
        accZHistory.removeAll()
        gyroXHistory.removeAll()
        gyroYHistory.removeAll()
        gyroZHistory.removeAll()
        
        // 使用回调方式（iOS 16 必须用这种方式）
        print("🎬 [SensorRecorder] 调用 startDeviceMotionUpdates(to:withHandler:)")
        print("📝 [SensorRecorder] 注意：iOS 16 上 deviceMotion 属性可能为 nil，必须使用回调")
        print("💡 [SensorRecorder] 请确保 AirPods 已佩戴并摇动头部触发数据")
        
        // 关键：使用 OperationQueue.main 而不是 .main
        headphoneMotionManager.startDeviceMotionUpdates(to: OperationQueue.main) { [weak self] motion, error in
            guard let self = self else { return }
            
            // 详细日志
            if self.sampleCount == 0 {
                print("📥 [SensorRecorder] 收到第一次回调")
                print("   motion: \(motion != nil ? "有数据" : "nil")")
                print("   error: \(error?.localizedDescription ?? "无错误")")
            }
            
            if let error = error {
                print("❌ [SensorRecorder] 数据获取错误: \(error.localizedDescription)")
                return
            }
            
            guard let motion = motion else {
                if self.sampleCount == 0 {
                    print("⚠️ [SensorRecorder] motion 为 nil")
                }
                return
            }
            
            // 首次接收到数据
            if self.sampleCount == 0 {
                print("✅ [SensorRecorder] 开始接收数据")
                print("   陀螺仪: x=\(String(format: "%.4f", motion.rotationRate.x))")
                print("   加速度: x=\(String(format: "%.4f", motion.userAcceleration.x))")
                print("   重力: z=\(String(format: "%.4f", motion.gravity.z))")
            }
            
            self.saveMotionData(motion)
        }
        
        // 5秒后检查是否收到回调
        DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { [weak self] in
            guard let self = self else { return }
            if self.sampleCount == 0 {
                print("❌ [SensorRecorder] 5秒后仍未收到任何回调！")
                print("👉 [SensorRecorder] 可能原因：")
                print("   1. AirPods 没有佩戴（必须佩戴在头上）")
                print("   2. 需要摇动头部才能触发数据")
                print("   3. AirPods 型号不支持（需要 AirPods 3代/Pro/Max）")
                print("   4. 运行在模拟器上（必须真机）")
            } else {
                print("✅ [SensorRecorder] 已成功收到 \(self.sampleCount) 个回调")
            }
        }
    }
    
    /// 停止录制
    func stop() {
        guard isRunning else { return }
        
        headphoneMotionManager.stopDeviceMotionUpdates()
        isRunning = false
        
        print("⏹️ [SensorRecorder] 已停止录制，采集了 \(sampleCount) 个样本")
        print("📊 [SensorRecorder] linSamples 数量: \(linSamples.count)")
        
        // 检查前几个 linSamples 的值
        if linSamples.count > 0 {
            let sample = linSamples[0]
            print("📊 [SensorRecorder] 第1个 linSample: ax_lin=\(String(format: "%.6f", sample.ax_lin)), ay_lin=\(String(format: "%.6f", sample.ay_lin)), az_lin=\(String(format: "%.6f", sample.az_lin))")
        }
        if linSamples.count > 10 {
            let sample = linSamples[10]
            print("📊 [SensorRecorder] 第11个 linSample: ax_lin=\(String(format: "%.6f", sample.ax_lin)), ay_lin=\(String(format: "%.6f", sample.ay_lin)), az_lin=\(String(format: "%.6f", sample.az_lin))")
        }
    }
    
    // MARK: - 数据处理
    
    /// 保存运动数据（直接在回调中调用）
    private func saveMotionData(_ motion: CMDeviceMotion) {
        let timestamp = Date().timeIntervalSince1970
        
        // 1. 获取加速度计数据（包含重力）
        let gravity = motion.gravity
        let userAcc = motion.userAcceleration
        let ax = gravity.x + userAcc.x
        let ay = gravity.y + userAcc.y
        let az = gravity.z + userAcc.z
        
        // 2. 获取陀螺仪数据（旋转速率，rad/s）
        let rotationRate = motion.rotationRate
        let wx = rotationRate.x
        let wy = rotationRate.y
        let wz = rotationRate.z
        
        // 3. 更新实时数据（供 UI 使用）
        currentAccX = ax
        currentAccY = ay
        currentAccZ = az
        currentGyroX = wx
        currentGyroY = wy
        currentGyroZ = wz
        
        // 4. 更新历史数据（用于图表显示）
        accXHistory.append(ax)
        accYHistory.append(ay)
        accZHistory.append(az)
        gyroXHistory.append(wx)
        gyroYHistory.append(wy)
        gyroZHistory.append(wz)
        
        // 保持历史数据在最大点数以内
        if accXHistory.count > maxHistoryPoints {
            accXHistory.removeFirst()
            accYHistory.removeFirst()
            accZHistory.removeFirst()
            gyroXHistory.removeFirst()
            gyroYHistory.removeFirst()
            gyroZHistory.removeFirst()
        }
        
        // 4. 保存原始数据（加速度计 + 陀螺仪）
        let rawSample = RawSample(
            t: timestamp,
            ax: ax, ay: ay, az: az,
            wx: wx, wy: wy, wz: wz
        )
        rawSamples.append(rawSample)
        sampleCount = rawSamples.count
        
        // 首次和每 100 个样本打印一次
        if sampleCount == 1 {
            print("✅ [SensorRecorder] 首个样本已采集")
        } else if sampleCount % 100 == 0 {
            print("📊 [SensorRecorder] 已采集 \(sampleCount) 个样本")
        }
        
        // 5. 计算线性加速度（去除重力，转换到世界坐标系）
        let R = motion.attitude.rotationMatrix
        let ax_lin = R.m11 * userAcc.x + R.m12 * userAcc.y + R.m13 * userAcc.z
        let ay_lin = R.m21 * userAcc.x + R.m22 * userAcc.y + R.m23 * userAcc.z
        let az_lin = R.m31 * userAcc.x + R.m32 * userAcc.y + R.m33 * userAcc.z
        
        // 调试：每100个样本打印一次数据
        if sampleCount % 100 == 0 {
            print("📐 [SensorRecorder] 样本 #\(sampleCount):")
            print("   userAcc: x=\(String(format: "%.6f", userAcc.x)), y=\(String(format: "%.6f", userAcc.y)), z=\(String(format: "%.6f", userAcc.z))")
            print("   gravity: x=\(String(format: "%.6f", gravity.x)), y=\(String(format: "%.6f", gravity.y)), z=\(String(format: "%.6f", gravity.z))")
            print("   lin (转换后): x=\(String(format: "%.6f", ax_lin)), y=\(String(format: "%.6f", ay_lin)), z=\(String(format: "%.6f", az_lin))")
        }
        
        let linSample = LinSample(
            t: timestamp,
            ax_lin: ax_lin,
            ay_lin: ay_lin,
            az_lin: az_lin
        )
        linSamples.append(linSample)
        
        // 验证线性数据是否被记录
        if sampleCount == 1 {
            print("✅ [SensorRecorder] linSamples 数量: \(linSamples.count)")
        }
    }
    
    // MARK: - Export CSV (Excel compatible)
    @discardableResult
    func exportCSVs(userName: String, note: String) throws -> [URL] {
        let safeName = sanitize(fileSegment: userName)
        let safeNote = sanitize(fileSegment: note.isEmpty ? "未备注" : note)
        let rawFileName = "\(safeName)_\(safeNote)_1.csv"
        let linFileName = "\(safeName)_\(safeNote)_2.csv"
        
        let rawCSV = buildRawCSV()
        let linCSV = buildLinCSV()
        
        let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let rawURL = dir.appendingPathComponent(rawFileName)
        let linURL = dir.appendingPathComponent(linFileName)
        
        try rawCSV.data(using: .utf8)?.write(to: rawURL, options: .atomic)
        try linCSV.data(using: .utf8)?.write(to: linURL, options: .atomic)
        
        return [rawURL, linURL]
    }
    
    private func buildRawCSV() -> String {
        var s = "timestamp,ax,ay,az,wx,wy,wz\n"
        for r in rawSamples {
            s += String(format: "%.6f,%.6f,%.6f,%.6f,%.6f,%.6f,%.6f\n", r.t, r.ax, r.ay, r.az, r.wx, r.wy, r.wz)
        }
        return s
    }
    
    private func buildLinCSV() -> String {
        var s = "timestamp,ax_lin,ay_lin,az_lin\n"
        print("📝 [SensorRecorder] 开始构建 Lin CSV，linSamples 数量: \(linSamples.count)")
        
        for (index, v) in linSamples.enumerated() {
            s += String(format: "%.6f,%.6f,%.6f,%.6f\n", v.t, v.ax_lin, v.ay_lin, v.az_lin)
            
            // 打印前3个样本的内容
            if index < 3 {
                print("📝 [SensorRecorder] Lin CSV 第\(index+1)行: t=\(String(format: "%.6f", v.t)), ax_lin=\(String(format: "%.6f", v.ax_lin)), ay_lin=\(String(format: "%.6f", v.ay_lin)), az_lin=\(String(format: "%.6f", v.az_lin))")
            }
        }
        
        print("📝 [SensorRecorder] Lin CSV 构建完成，总行数: \(linSamples.count + 1)")
        return s
    }
    
    private func sanitize(fileSegment: String) -> String {
        let illegal = CharacterSet(charactersIn: "/\\?%*|\"<>:")
        let cleaned = fileSegment.components(separatedBy: illegal).joined(separator: "_")
        return cleaned.replacingOccurrences(of: "\n", with: " ").replacingOccurrences(of: "\r", with: " ")
    }
}

// MARK: - CMHeadphoneMotionManagerDelegate
extension SensorRecorder: CMHeadphoneMotionManagerDelegate {
    func headphoneMotionManagerDidConnect(_ manager: CMHeadphoneMotionManager) {
        print("🎧 [SensorRecorder] AirPods 已连接")
    }
    
    func headphoneMotionManagerDidDisconnect(_ manager: CMHeadphoneMotionManager) {
        print("🔌 [SensorRecorder] AirPods 已断开")
    }
}


